package datastruct.list.impl;

import datastruct.list.inter.IListConsumer;
import datastruct.list.inter.IExpected;
import datastruct.list.inter.IJoList;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;

public class JoListII implements IJoList {

    private List<String> list;

    private AtomicInteger listSize;

    public JoListII() {
        list = Collections.synchronizedList(new LinkedList<String>());
        listSize = new AtomicInteger(0);
    }

    public static JoListII makeListII() {
        return new JoListII();
    }

    @Override
    public void add(String val) {
        list.add(val);
        listSize.getAndIncrement();
    }

    public void addFirst(String val) {
        list.add(0, val);
        listSize.getAndIncrement();
    }

    @Override
    public String get(int index) {
        if (index < 0 || index >= Len()) {
            return null;
        }
        synchronized (list) {
            ListIterator<String> iterator = list.listIterator(index);
            return iterator.next();
        }
    }

    @Override
    public  boolean set(int index, String val) {
        if (index >= Len()) {
            return false;
        }
        synchronized (list) {
            ListIterator<String> iterator = list.listIterator(index);
            iterator.next();
            iterator.set(val);
            return true;
        }

    }

    @Override
    public  void insert(int index, String val, boolean isBefore) {
        if (index < 0 || index > listSize.intValue()) {
            return;
        }
        synchronized (list) {
            ListIterator<String> iterator = list.listIterator(index);
            if (isBefore) {
                iterator.add(val);
                listSize.getAndIncrement();
            } else {
                if (iterator.hasNext()) {
                    iterator.next();
                }
                iterator.add(val);
                listSize.getAndIncrement();
            }
        }

//        if (index <= 0) {
//            index = 0;
//        }
//
//        if (!isBefore) {
//            index++;
//        }
//
//        if (index >= listSize.intValue()) {
//            list.add(val);
//            listSize.getAndIncrement();
//            return;
//        }
//
//        list.add(index, val);
//        listSize.getAndIncrement();
    }

    @Override
    public int Remove(String val, int count) {
        synchronized (list) {
            int removed = 0;
            boolean result = true;
            ListIterator<String> iterator = list.listIterator(0);
            while (iterator.hasNext()) {
                if (iterator.next().equals(val)) {
                    iterator.remove();
                    removed++;
                    listSize.getAndDecrement();
                    if (removed == count) {
                        break;
                    }
                }
            }
            return removed;
        }
    }

    @Override
    public  int RemoveFrom(int direction, int count, String target) {
        count = Math.min(count, listSize.intValue());
        if (direction >= 0) {
            return Remove(target, count);
        }

        // 倒序遍历
        synchronized (list) {
            int removed = 0;
            ListIterator<String> iterator = list.listIterator(listSize.intValue());
            while (iterator.hasPrevious()) {
                if (iterator.previous().equals(target)) {
                    iterator.remove();
                    removed++;
                    listSize.getAndDecrement();
                    if (removed == count) {
                        break;
                    }
                }
            }
            return removed;
        }
    }

    @Override
    public  String RemoveFirst() {
        if (list.isEmpty()) {
            return null;
        }
        listSize.getAndDecrement();
        return list.remove(0);
    }

    @Override
    public  String RemoveLast() {
        if (list.isEmpty()) {
            return null;
        }
        listSize.getAndDecrement();
        return list.remove(list.size()-1);
    }

    @Override
    public  int Len() {
        return listSize.intValue();
    }

    @Override
    public  void forEach(boolean desc, IListConsumer iConsumer) {
        int size = listSize.intValue();
        synchronized (list) {
            ListIterator<String> iterator = desc ? list.listIterator(listSize.intValue()) : list.listIterator(0);
            if (desc) {
                int i = listSize.intValue() - 1;
                while (iterator.hasPrevious()) {
                    if (!iConsumer.consumer(i, iterator.previous())) {
                        return;
                    }
                    i--;
                }
            } else {
                int i = 0;
                while (iterator.hasNext()) {
                    if (!iConsumer.consumer(i, iterator.next())) {
                        return;
                    }
                    i++;
                }
            }
        }
    }

    @Override
    public  boolean contains(String obj) {
        return list != null && list.contains(obj);
    }

    // [start, stop) 左闭右开
    @Override
    public  String[] range(int start, int end) {
        if (start < 0 || start >= listSize.intValue()) {
            return null;
        }

        if (end < start || end > listSize.intValue()) {
            return null;
        }

//        return list.subList(start, end).toArray(new String[0]);

        synchronized (list) {
            ListIterator<String> iterator = list.listIterator(start);
            int setSize = end - start;

            int  i = 0;
            String[] ret = new String[setSize];
            while (iterator.hasNext() && i < setSize) {
                ret[i++] = iterator.next();
            }
            return ret;
        }
    }

    @Override
    public  int indexOfVal(String obj) {
        return list.indexOf(obj);
    }

    public static void main(String[] args) {
        JoList ls = new JoList();
        ls.add("A");
        ls.add("B");
        ls.add("C");
        ls.add("D");

        int index = ls.indexOfVal("C");
        System.out.println(index);


    }
}
